//Copyright (c) 2006-2007 Microsoft Corporation.  All rights reserved
using System;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;

using InvocationFramework.Core;

namespace InvocationFramework.Core.ProxyFactory
{
    /// <summary>
    /// Intercepta las llamadas a los metodos de un proxu generado con <seealso cref="RemotingProxyGenerator"/> 
    /// y las reemplaza por invocaciones a servicios utilizando la infraestructura de SIF
    /// </summary>
    /// <typeparam name="T">Tipo del proxy a interceptar</typeparam>
    /// <author>Rodolfo Finochietti 03/02/2006 23.25</author>
    internal class RemotingProxyInterceptor<T> : RealProxy where T : class
    {
        #region Private Vars

        /// <summary>
        /// Nombre del servicio al que se invocara en la intercepcion
        /// </summary>
        private string _serviceName;

        #endregion

        #region Constructors

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="serviceName">Nombre del servicio al que se invocara en la intercepcion</param>
        public RemotingProxyInterceptor( string serviceName ) : base( typeof( T ) )
        {
            _serviceName = serviceName;
        }

        #endregion

        #region Public Methods
        
        /// <summary>
        /// Devuelve un proxy del tipo requerido
        /// </summary>
        /// <remarks>
        /// Se podria utilizar el metodo de la clase base <seealso cref="RealProxy"/> pero habria que castear en el llamador
        /// </remarks>
        /// <returns>El proxy del tipo requerido</returns>
        public T CreateProxy( )
        {
            return base.GetTransparentProxy( ) as T;
        }

        /// <summary>
        /// Permite realizar la intercepcion en donde se invoca al servicio real via SIF
        /// </summary>
        /// <param name="msg">El mensaje con los datos del metodo a interceptar</param>
        /// <returns>Un mensaje con la respuesta de la intercepcion</returns>
        public override IMessage Invoke( IMessage msg )
        {
            object result = null;

            //Si es un llamada a un metodo lo intercepto
            IMethodCallMessage call = msg as IMethodCallMessage;
            if ( call != null )
                result = ServiceCaller.Execute( _serviceName, call.MethodName, call.Args ); //Invoco al servicio usando SIF

            //Devuelvo el resultado de la invocacion del servicio
            return new ReturnMessage( result, null, 0, null, call );
        }
    
        #endregion
    }
}